:- ['tools.pro','globalConstraints.pro'].


/*
pairwiseGenerator(LstFeature,Matrix,PWCTRLST,RANKLST).

A in -1..0, B in -1.. 0 , C in -1..0, LstFeature = [A,B,C],CA = [A1,A2,A3], CB = [B1,B2,B3], CC =[C1,C2,C3] , Matrix = [CA,CB,CC], 
pairwiseGenerator(LstFeature,Matrix,PWCTRLST,RANKLST), 
[pairwise(-1,-1,CA,CB,_A),pairwise(-1,0,CA,CB,_B),pairwise(0,-1,CA,CB,_C),pairwise(0,0,CA,CB,_D),
pairwise(-1,-1,CA,CC,_E),pairwise(-1,0,CA,CC,_F),pairwise(0,-1,CA,CC,_G),pairwise(0,0,CA,CC,_H),
pairwise(-1,-1,CB,CC,_I),pairwise(-1,0,CB,CC,_J),pairwise(0,-1,CB,CC,_K),pairwise(0,0,CB,CC,_L)]
RANKLST = [[_A,_B,_C,_D],[_E,_F,_G,_H],[_I_,_J,_K,_L]].

A in -1..0, B in -1.. 0 , C in -1..0,mutex(A,B),mutex(B,C), LstFeature = [A,B,C],CA = [A1,A2,A3], CB = [B1,B2,B3], CC =[C1,C2,C3] , Matrix = [CA,CB,CC], 
pairwiseGenerator(LstFeature,Matrix,PWCTRLST,RANKLST)
*/

pairwiseGenerator([A|R],[CA|CR],PWCTRLST,RANKLST3) :-
     R\= [],   pairwiseGenerator2(A,R,CA,CR,PWCTRLST1,RANKLST1),
        pairwiseGenerator(R,CR,PWCTRLST2,RANKLST2),
        append(PWCTRLST1,PWCTRLST2,PWCTRLST) ,
        append(RANKLST1,RANKLST2,RANKLST3) .

pairwiseGenerator([_|[]],_,[],[]).

        
        /*
        
        
| ?- A in -1..0, B in -1.. 0 , C in -1..0, LstFeature = [A,B,C],CA = [A1,A2,A3], CB = [B1,B2,B3], CC =[C1,C2,C3] , Matrix = [CA,CB,CC], 
pairwiseGenerator(LstFeature,Matrix,PWCTRLST,RANKLST).
CA = [A1,A2,A3],
CB = [B1,B2,B3],
CC = [C1,C2,C3],
Matrix = [[A1,A2,A3],[B1,B2,B3],[C1,C2,C3]],
RANKLST = [[_A,_B,_C,_D],[_E,_F,_G,_H],[_I,_J,_K,_L]],
PWCTRLST = [pairwise(-1,-1,[A1,A2,A3],[B1,B2,B3],_A),pairwise(-1,0,[A1,A2,A3],[B1,B2,B3],_B),pairwise(0,-1,[A1,A2,A3],[B1,B2,B3],_C),pairwise(0,0,[A1,A2,A3],[B1,B2,B3],_D),pairwise(-1,-1,[A1,A2,A3],[C1,C2,C3],_E),pairwise(-1,0,[A1,A2,A3],[C1,C2,C3],_F),pairwise(0,-1,[A1,A2,A3],[C1,C2,C3],_G),pairwise(0,0,[A1,A2|...],[C1,C2|...],_H),pairwise(-1,-1,[B1|...],[C1|...],_I),pairwise(...)|...],
LstFeature = [A,B,C],
A in-1..0,
B in-1..0,
C in-1..0 ? ;
no
% source_info
            */

pairwiseGenerator2(A,[B|R],CA,[CB|CR],PWCTRLST,RANKLST) :-
        pairwiseConstraintsGenerator(A,B,CA,CB,PWCTRLST1,RANKLST1),
        pairwiseGenerator2(A,R,CA,CR,PWCTRLST2,RANKLST2),
        append(PWCTRLST1,PWCTRLST2,PWCTRLST) ,
        RANKLST = [RANKLST1|RANKLST2].

pairwiseGenerator2(_,[],_,[],[],[]).


/*

Starting point : Takes Two finite domains variables and generate corresponding pw constraints
pairwsiseConstraintsGenerator(+A,+B,+CA,+CB,-PWCTRLST,-RANKLST)
      A : finite domain variable (in -1 .. 0)
      B : finite domain variable (in -1 .. 0)
      CA : A matrix Column
      CB : B matrix Column
      PWCTRLST : list of pairwiseconstraints
      RANKLST : list of matrix ranks      
      
      
A in -1..0, B in -1..0, CA = [A1,A2,A3], CB = [B1,B2,B3],pairwiseConstraintsGenerator(A,B,CA,CB,PWCTRLST,RANKLST),
PWCTRLST = [pairwise(-1,-1,CA,CB,I1),pairwise(-1,0,CA,CB,I2),pairwise(0,-1,CA,CB,I3),pairwise(0,0,CA,CB,I4)],
RANKLST = [I1,I2,I3,I4]. 
Order doesn't matter                 
*/

pairwiseConstraintsGenerator(A,B,CA,CB,PWCTRLST,RANKLST) :-
                domainToList(A,LA),
                avalueGenerator(A,LA,B,CA,CB,PWCTRLST,RANKLST).
        

/*
Test
   
   | ?- A in -1..0, B in -1..0, CA = [A1,A2,A3], CB = [B1,B2,B3],pairwiseConstraintsGenerator(A,B,CA,CB,PWCTRLST,RANKLST).
CA = [A1,A2,A3],
CB = [B1,B2,B3],
RANKLST = [_A,_B,_C,_D],
PWCTRLST = [pairwise(-1,-1,[A1,A2,A3],[B1,B2,B3],_A),pairwise(-1,0,[A1,A2,A3],[B1,B2,B3],_B),pairwise(0,-1,[A1,A2,A3],[B1,B2,B3],_C),pairwise(0,0,[A1,A2,A3],[B1,B2,B3],_D)],
A in-1..0,
B in-1..0 ? ;
no
% source_info
            
Constraint handling :
                    % source_info
| ?- A in -1..0, B in -1..0,mutex(A,B), CA = [A1,A2,A3], CB = [B1,B2,B3],pairwiseConstraintsGenerator(A,B,CA,CB,PWCTRLST,RANKLST).
CA = [A1,A2,A3],
CB = [B1,B2,B3],
RANKLST = [_A,_B,_C],
PWCTRLST = [pairwise(-1,-1,[_D,_E,_F],[_G,_H,_I],_A),pairwise(-1,0,[_D,_E,_F],[_G,_H,_I],_B),pairwise(0,-1,[_J,_K,_L],[_M,_N,_O],_C)],
A in-1..0,
B in-1..0 ? ;
no
% source_info
            OK
*/
/*
domainToList(+A,-L).
A in -1..0, domainToList(A,L),L =[-1,0].
No backtrack        
*/

domainToList(A,L) :-
          fd_dom(A,RA),range_to_fdset(RA,SA),fdset_to_list(SA,L).

/*
| ?- A in -1..0, domainToList(A,L),L =[-1,0].
L = [-1,0],
A in-1..0 ? 
*/



/*
avalueGenerator(LA,B,CA,CB,PWCTRLST,RANKLST).
LA : int List
      B : finite domain variable (in -1 .. 0)
      CA : A matrix Column
      CB : B matrix Column
      PWCTRLST : list of pairwiseconstraints
      RANKLST : list of matrix ranks    
      
      A = [-1,0], B in -1..0, CA = [A1,A2,A3], CB = [B1,B2,B3],avalueGenerator(A,B,CA,CB,PWCTRLST,RANKLST),
PWCTRLST = [pairwise(-1,-1,CA,CB,I1),pairwise(-1,0,CA,CB,I2),pairwise(0,-1,CA,CB,I3),pairwise(0,0,CA,CB,I4)],
RANKLST = [I1,I2,I3,I4]. 
*/

avalueGenerator(_,[],_,_,_,[],[]).
avalueGenerator(A,[VA|R],B,CA,CB,PWCTRLST,RANKLST) :-
        \+(\+(callRec([A = VA,    pairListGenerator(VA,B,PairList),assert(p1(PairList))]))),
        p1(PairList),pairsGeneretor(PairList,CA,CB,PWCTRLST1,RANKLST1),retract(p1(_)),
        avalueGenerator(A,R,B,CA,CB,PWCTRLST2,RANKLST2),
        append(PWCTRLST1,PWCTRLST2,PWCTRLST),
        append(RANKLST1,RANKLST2,RANKLST).

/* Test : 

| ?-  A in -1..0 ,LA = [-1,0], B in -1..0, CA = [A1,A2,A3], CB = [B1,B2,B3],avalueGenerator(A,LA,B,CA,CB,PWCTRLST,RANKLST).
CA = [A1,A2,A3],
CB = [B1,B2,B3],
LA = [-1,0],
RANKLST = [_A,_B,_C,_D],
PWCTRLST = [pairwise(-1,-1,[_E,_F,_G],[_H,_I,_J],_A),pairwise(-1,0,[_E,_F,_G],[_H,_I,_J],_B),pairwise(0,-1,[_K,_L,_M],[_N,_O,_P],_C),pairwise(0,0,[_K,_L,_M],[_N,_O,_P],_D)],
A in-1..0,
B in-1..0 ? ;
no
% source_info
 */

/*
pairListGenerator(VA,B,PairList) 
Va : int
 B : FiniteDomaine Variable
 PairList : list of pairs between VA and B
VA = 1, B in -1..0, pairListGenerator(VA,B,PairList) ,PairList = [[1,-1],[1,0]].
*/
pairListGenerator(VA,B,PairList) :-
        domainToList(B,LB),
        pairListUnitGenerator(VA,LB,PairList).

/*
| ?- VA = 1, B in -1..0, pairListGenerator(VA,B,PairList).
VA = 1,
PairList = [[1,-1],[1,0]],
B in-1..0 ? ;
no
% source_info
*/

/*
pairListUnitGenerator(VA,LB,PairList) 
Va : int
 LB : int List
 PairList : list of pairs between VA and B
VA = 1, LB = [-1,0], pairListUnitGenerator(VA,LB,PairList) ,PairList = [[-1,-1],[-1,0]].
*/

 pairListUnitGenerator(_,[],[]).
 pairListUnitGenerator(VA,[B|R],[[VA,B]|Res]):-
                      pairListUnitGenerator(VA,R,Res).                              

/*
  
| ?- VA = 1, LB = [-1,0], pairListUnitGenerator(VA,LB,PairList).
LB = [-1,0],
VA = 1,
PairList = [[1,-1],[1,0]] ? ;
no
% source_info
| ?- */


/*
 pairsGeneretor(PairList,CA,CB,PWCTRLST,RANKLST).
        PairList : [[-1,-1],[1,1]...]
      CA : A matrix Column
      CB : B matrix Column
      PWCTRLST : list of pairwiseconstraints
      RANKLST : list of matrix ranks              

PairList = [[1,1],[0,0]], CA = [A1,A2,A3], CB = [B1,B2,B3],pairsGeneretor(PairList,CA,CB,PWCTRLST,RANKLST),
PWCTRLST = [pairwise(0,0,CA,CB,I1),pairwise(1,1,CA,CB,I2)],
RANKLST = [I1,I2,I3,I4]. 
Order doesn't matter        
No backtrack         
*/

 pairsGeneretor([],_,_,[],[]).
 pairsGeneretor([[VA,VB]|R],CA,CB,PWCTRLST3,RANKLST3) :-
        PWCTRLST = [pairwise(I,(CA,CB),(VA,VB))],
        RANKLST = [I],
        pairsGeneretor(R,CA,CB,PWCTRLST2,RANKLST2),
        append(PWCTRLST,PWCTRLST2,PWCTRLST3),
        append(RANKLST,RANKLST2,RANKLST3).

/*
| ?- PairList = [[1,1],[0,0]], CA = [A1,A2,A3], CB = [B1,B2,B3],pairsGeneretor(PairList,CA,CB,PWCTRLST,RANKLST).
CA = [A1,A2,A3],
CB = [B1,B2,B3],
RANKLST = [_A,_B],
PairList = [[1,1],[0,0]],
PWCTRLST = [pairwise(1,1,[A1,A2,A3],[B1,B2,B3],_A),pairwise(0,0,[A1,A2,A3],[B1,B2,B3],_B)] ? ;
no
% source_info
| ?- 
*/



contrainteFD(M,LF) :- nbligne(M,I), contrainteFD1(M,LF,I).

contrainteFD1(M,LF,I) :- I > 0, ligne(M,I,L), validLine(LF,L),I2 is I -1, contrainteFD1(M,LF,I2).
contrainteFD1(_,_,0).

/*

LF = [A,B,C],domain(LF,-1,0),mutex(A,B),Values = [0,0,0],  validLine(LF,Values)
*/

validLine(LF,Valeur) :-lineConstraint(Valeur,_,LF).
   













